0%

ML_DL 中样本不均衡问题处理方式

发表于 2016-04-30 |

机器学习或者深度学习中常常会遇到数据的类别不平衡(class imbalance),也叫数据偏斜(class skew)。以常见的二分类问题为例,我们希望预测病人是否得了某种罕见疾病。但在历史数据中,阳性的比例可能很低(如百分之 0.1)。在这种情况下,学习出好的分类器是很难的,而且在这种情况下得到结论往往也是很具迷惑性的。再比如在 CTR 预估中,WAP 上的 CTR 通常在千分之几,APP 上 CTR 也就百分之一二,意味着 PV 远远要大于 Click。

以上面提到的场景来说,如果我们的分类器总是预测一个人未患病,即预测为反例,那么我们依然有高达 99.9% 的预测准确率。然而这种结果是没有意义的,那么有效在数据不平衡的情况下评估分类器呢?

当然,本文最终希望解决的问题是:在数据偏斜的情况下,如何得到一个不错的分类器?如果可能,是否可以找到一个较为简单的解决方法,而规避复杂的模型、数据处理,降低我们的工作量。

对于平衡的数据,我们一般都用准确率(accuracy),也就是(1 - 误分率)作为一般的评估标准。这种标准的默认假设前提是:“数据是平衡的,正例与反例的重要性一样,二分类器的阈值是 0.5。” 在这种情况下,用准确率来对分类器进行评估是合理的。

而当数据不平衡时,准确率就非常具有迷惑性,而且意义不大。下面给出几种主流的评估方法:

  • ROC 是一种常见的替代方法,全名 receiver operating curve,计算 ROC 曲线下的面积是一种主流方法
  • Precision-recall curve 和 ROC 有相似的地方,但定义不同,计算此曲线下的面积也是一种方法
  • Precision@n 是另一种方法,是指将分类阈值设定得到恰好 n 个正例时分类器的 precision
  • Average precision 也叫做平均精度,主要描述了 precision 的一般表现,在异常检测中有时候会用
  • 直接使用 Precision 也是一种想法,但此时的假设是分类器的阈值是 0.5,因此意义不大

至于哪种方法更好,一般来看我们在极端数据不平衡中更在意 “少数的类别”,因此 ROC 不像 precision-recall curve 那样更具有吸引力。在这种情况下,Precision-recall curve 不失为一种好的评估标准。还有一种做法是,仅分析 ROC 曲线左边的一小部分,从这个角度看和 precision-recall curve 有很高的相似性。

同理,因为我们更在意罕见的正例,因此 precision 尤为重要,因此 average precision (macro)也是常见的评估标准。此处特意要提醒两点:(1)没有特殊情况,不要用准确率(accuracy),一般都没什么帮助。(2)如果使用 precision,请注意调整分类阈值,precision@n 更有意义。

对于数据不平衡的研究已经有很多年了,下面结合我的了解举几个简单的例子:

  • 对数据进行采用的过程中通过相似性同时生成并插样 “少数类别数据”,叫做 SMOTE 算法
  • 对数据先进行聚类,再将大的簇进行随机欠采样或者小的簇进行数据生成
  • 把监督学习变为无监督学习,舍弃掉标签把问题转化为一个无监督问题,如异常检测
  • 先对多数类别进行随机的欠采样,并结合 boosting 算法进行集成学习

上面提到的算法比较偏理论,实际应用中的最简单的算法无外乎三种:

  • 对较多的那个类别进行欠采样 (under-sampling),舍弃一部分数据,使其与较少类别的数据相当;
  • 对较少的类别进行过采样 (over-sampling),重复使用一部分数据,使其与较多类别的数据相当;
  • 阈值调整(threshold moving),将原本默认为 0.5 的阈值调整到 较少类别 /(较少类别 + 较多类别)即可;

当然很明显我们可以看出,第一种和第二种方法都会明显的改变数据分布,我们的训练数据假设不再是真实数据的无偏表述。在第一种方法中,我们浪费了很多数据。而第二类方法中有无中生有或者重复使用了数据,会导致过拟合的发生。

因此欠采样的逻辑中往往会结合集成学习来有效的使用数据,假设正例数据 n,而反例数据 m 个。我们可以通过欠采样,随机无重复的生成(k=n/m)个反例子集,并将每个子集都与相同正例数据合并生成 k 个新的训练样本。我们在 k 个训练样本上分别训练一个分类器,最终将 k 个分类器的结果结合起来,比如求平均值。

但不难看出,其实这样的过程是需要花时间处理数据和编程的,对于很多知识和能力有限的人来说难度比较大。特此推荐两个简单易行且效果中上的做法:

  • 简单的调整阈值,不对数据进行任何处理。此处特指将分类阈值从 0.5 调整到正例比例;
  • 使用现有的集成学习分类器,如随机森林或者 xgboost,并调整分类阈值;

以上总结是个人的一些思考以及前人的一些总结,仅供参考。